using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using JigLibX;
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Physics;

namespace PhysicObjects
{
    class TriangleMeshObject : PhysicObject
    {
        TriangleMesh triangleMesh;

        public TriangleMeshObject(Game game, Model model, Matrix orientation, Vector3 position)
            : base(game, model)
        {
            body = new Body();
            collision = new CollisionSkin(body);

            triangleMesh = new TriangleMesh();

            List<Vector3> vertexList = new List<Vector3>();
            List<TriangleVertexIndices> indexList = new List<TriangleVertexIndices>();

            ExtractData(vertexList, indexList, model);

            triangleMesh.CreateMesh(vertexList,indexList, 4, 1.0f);
            collision.AddPrimitive(triangleMesh,new MaterialProperties(0.8f,0.7f,0.6f));
            body.CollisionSkin = collision;
            body.EnableBody();
        }


        /// <summary>
        /// Helper Method to get the vertex and index List from the model.
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="indices"></param>
        /// <param name="model"></param>
        public void ExtractData(List<Vector3> vertices, List<TriangleVertexIndices> indices,Model model)
        {
            // Suck triangles out of the level model to be used as collision geometry
            {
                foreach (ModelMesh m in model.Meshes)
                {
                    foreach (ModelMeshPart meshPart in m.MeshParts)
                    {
                        var vertexDeclaration = meshPart.VertexBuffer.VertexDeclaration;
                        var vertexElements = vertexDeclaration.GetVertexElements();

                        var positionElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.Position);
                        if (positionElement.VertexElementFormat != VertexElementFormat.Vector3)
                            throw new NotSupportedException();  

                        var positions = new Vector3[meshPart.NumVertices];
                        meshPart.VertexBuffer.GetData(
                            meshPart.VertexOffset * vertexDeclaration.VertexStride + positionElement.Offset,
                            positions,
                            0,
                            meshPart.NumVertices,
                            vertexDeclaration.VertexStride);

                        foreach (Vector3 ps in positions)
                        {
                            vertices.Add(ps);
                        }

                        var indexElementSize = (meshPart.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits) ? 2 : 4;
                        if (indexElementSize != 2)
                            throw new NotSupportedException();

                        var i = new short[meshPart.PrimitiveCount * 3];
                        meshPart.IndexBuffer.GetData(
                            meshPart.StartIndex * 2,
                            i,
                            0,
                            meshPart.PrimitiveCount * 3);

                        for (int ib = 0; ib != meshPart.PrimitiveCount; ++ib)
                        {
                            indices.Add(new JigLibX.Geometry.TriangleVertexIndices(i[ib * 3 + 0], i[ib * 3 + 2], i[ib * 3 + 1]));
                        }
                    }
                }
            }
        }

        
    }
}
